package com.fly.studio.home.app.concurrency;

import com.jd.platform.async.wrapper.WorkerWrapper;
import org.springframework.util.CollectionUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author fuliying3
 * @date 2022/09/22 10:13:00
 */
public class WorkerWrapperHelper<P, R> {

    private static ParWorkerFactory workerFactory = new ParWorkerFactory();

    private Map<String, WorkerWrapper<P, R>> allWrappers = new HashMap<>(16);

    WorkerWrapper<P, R>[] buildWorkerWrappers(List<Server> servers, P p) {
        WorkerWrapper<P, R>[] workerWrappers = getRootWorkerWrappers(servers, p);
        buildDepends(servers.stream().filter(server -> !CollectionUtils.isEmpty(server.getDepends())).collect(Collectors.toList()), p);
        return workerWrappers;
    }

    private WorkerWrapper<P, R>[] getRootWorkerWrappers(List<Server> servers, P p) {
        int count = (int) servers.stream().filter(server -> CollectionUtils.isEmpty(server.getDepends())).count();
        WorkerWrapper<P, R>[] workerWrappers = new WorkerWrapper[count];
        for (int i = 0; i < count; i++) {
            for (Server server : servers) {
                if (!CollectionUtils.isEmpty(server.getDepends()) || allWrappers.containsKey(server.getName())) {
                    continue;
                }
                workerWrappers[i] = new WorkerWrapper.Builder<P, R>()
                        .id(server.getName())
                        .worker(workerFactory.getFloorWorker(server.getName()))
                        .param(p + server.getName())
                        .build();
                allWrappers.put(server.getName(), workerWrappers[i]);
                break;
            }
        }
        return workerWrappers;
    }

    private void buildDepends(List<Server> servers, P p) {
        if (CollectionUtils.isEmpty(servers)) {
            return;
        }
        next_server:
        for (Iterator<Server> iterator = servers.iterator(); iterator.hasNext(); ) {
            Server server = iterator.next();
            if (allWrappers.containsKey(server.getName())) {
                continue;
            }
            List<String> depends = server.getDepends();
            for (String depend : depends) {
                if (!allWrappers.containsKey(depend)) {
                    continue next_server;
                }
            }
            WorkerWrapper<P, R>[] dependWorkerWrappers = getDependWorkerWrappers(depends);
            WorkerWrapper<P, R> workerWrapper = new WorkerWrapper.Builder<P, R>()
                    .id(server.getName())
                    .worker(workerFactory.getFloorWorker(server.getName()))
                    .depend(dependWorkerWrappers)
                    .param(p + server.getName())
                    .build();
            allWrappers.put(server.getName(), workerWrapper);
            iterator.remove();
        }
        buildDepends(servers, p);
    }

    private WorkerWrapper<P, R>[] getDependWorkerWrappers(List<String> depends) {
        WorkerWrapper<P, R>[] dependWorkerWrappers = new WorkerWrapper[depends.size()];
        for (int i = 0; i < depends.size(); i++) {
            dependWorkerWrappers[i] = allWrappers.get(depends.get(i));
        }
        return dependWorkerWrappers;
    }
}
